{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>sepal length in cm</th>\n",
       "      <th>sepal width in cm</th>\n",
       "      <th>petal length in cm</th>\n",
       "      <th>petal width in cm</th>\n",
       "      <th>class label</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>5.1</td>\n",
       "      <td>3.5</td>\n",
       "      <td>1.4</td>\n",
       "      <td>0.2</td>\n",
       "      <td>Iris-setosa</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>4.9</td>\n",
       "      <td>3.0</td>\n",
       "      <td>1.4</td>\n",
       "      <td>0.2</td>\n",
       "      <td>Iris-setosa</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>4.7</td>\n",
       "      <td>3.2</td>\n",
       "      <td>1.3</td>\n",
       "      <td>0.2</td>\n",
       "      <td>Iris-setosa</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>4.6</td>\n",
       "      <td>3.1</td>\n",
       "      <td>1.5</td>\n",
       "      <td>0.2</td>\n",
       "      <td>Iris-setosa</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5.0</td>\n",
       "      <td>3.6</td>\n",
       "      <td>1.4</td>\n",
       "      <td>0.2</td>\n",
       "      <td>Iris-setosa</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   sepal length in cm  sepal width in cm  petal length in cm  \\\n",
       "0                 5.1                3.5                 1.4   \n",
       "1                 4.9                3.0                 1.4   \n",
       "2                 4.7                3.2                 1.3   \n",
       "3                 4.6                3.1                 1.5   \n",
       "4                 5.0                3.6                 1.4   \n",
       "\n",
       "   petal width in cm  class label  \n",
       "0                0.2  Iris-setosa  \n",
       "1                0.2  Iris-setosa  \n",
       "2                0.2  Iris-setosa  \n",
       "3                0.2  Iris-setosa  \n",
       "4                0.2  Iris-setosa  "
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 自己来定义列名\n",
    "feature_dict = {i:label for i,label in zip(\n",
    "                range(4),\n",
    "                  ('sepal length in cm',\n",
    "                  'sepal width in cm',\n",
    "                  'petal length in cm',\n",
    "                  'petal width in cm', ))}\n",
    "\n",
    "label_dict = {i:label for i,label in zip(\n",
    "                range(1,4),\n",
    "                  ('Setosa',\n",
    "                  'Versicolor',\n",
    "                  'Virginica'\n",
    "                 ))}\n",
    "import pandas as pd\n",
    "# 数据读取，大家也可以先下载下来直接读取\n",
    "df = pd.io.parsers.read_csv(\n",
    "    filepath_or_buffer='https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data',\n",
    "    header=None,\n",
    "    sep=',',\n",
    "    )\n",
    "# 指定列名\n",
    "df.columns = [l for i,l in sorted(feature_dict.items())] + ['class label']\n",
    "\n",
    "df.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"img/l1.png\" alt=\"FAO\" width=\"690\" align=\"left\">"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.preprocessing import LabelEncoder\n",
    "\n",
    "X = df[['sepal length in cm','sepal width in cm','petal length in cm','petal width in cm']].values\n",
    "y = df['class label'].values\n",
    "\n",
    "# 制作标签{1: 'Setosa', 2: 'Versicolor', 3:'Virginica'}\n",
    "enc = LabelEncoder()\n",
    "label_encoder = enc.fit(y)\n",
    "y = label_encoder.transform(y) + 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"img/l2.png\" alt=\"FAO\" width=\"290\" align=\"left\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 分别求三种鸢尾花数据在不同特征维度上的均值向量 mi\n",
    "<img src=\"img/l3.png\" alt=\"FAO\" width=\"390\">"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "均值类别 1: [5.006 3.418 1.464 0.244]\n",
      "\n",
      "均值类别 2: [5.936 2.77  4.26  1.326]\n",
      "\n",
      "均值类别 3: [6.588 2.974 5.552 2.026]\n",
      "\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "#设置小数点的位数\n",
    "np.set_printoptions(precision=4) \n",
    "#这里会保存所有的均值\n",
    "mean_vectors = []\n",
    "# 要计算3个类别\n",
    "for cl in range(1,4):\n",
    "    # 求当前类别各个特征均值\n",
    "    mean_vectors.append(np.mean(X[y==cl], axis=0))\n",
    "    print('均值类别 %s: %s\\n' %(cl, mean_vectors[cl-1]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 计算两个 4×4 维矩阵：类内散布矩阵和类间散布矩阵\n",
    "-  <img src=\"img/l5.png\" alt=\"FAO\" width=\"330\" >\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "类内散布矩阵:\n",
      " [[38.9562 13.683  24.614   5.6556]\n",
      " [13.683  17.035   8.12    4.9132]\n",
      " [24.614   8.12   27.22    6.2536]\n",
      " [ 5.6556  4.9132  6.2536  6.1756]]\n"
     ]
    }
   ],
   "source": [
    "# 原始数据中有4个特征\n",
    "S_W = np.zeros((4,4))\n",
    "# 要考虑不同类别，自己算自己的\n",
    "for cl,mv in zip(range(1,4), mean_vectors):\n",
    "    class_sc_mat = np.zeros((4,4))    \n",
    "    # 选中属于当前类别的数据\n",
    "    for row in X[y == cl]:\n",
    "        # 这里相当于对各个特征分别进行计算，用矩阵的形式\n",
    "        row, mv = row.reshape(4,1), mv.reshape(4,1)\n",
    "        # 跟公式一样\n",
    "        class_sc_mat += (row-mv).dot((row-mv).T)\n",
    "    S_W += class_sc_mat                             \n",
    "print('类内散布矩阵:\\n', S_W)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "-  <img src=\"img/l6.png\" alt=\"FAO\" width=\"430\" >"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "类间散布矩阵:\n",
      " [[ 63.2121 -19.534  165.1647  71.3631]\n",
      " [-19.534   10.9776 -56.0552 -22.4924]\n",
      " [165.1647 -56.0552 436.6437 186.9081]\n",
      " [ 71.3631 -22.4924 186.9081  80.6041]]\n"
     ]
    }
   ],
   "source": [
    "# 全局均值\n",
    "overall_mean = np.mean(X, axis=0)\n",
    "# 构建类间散布矩阵\n",
    "S_B = np.zeros((4,4))\n",
    "# 对各个类别进行计算\n",
    "for i,mean_vec in enumerate(mean_vectors):  \n",
    "    #当前类别的样本数\n",
    "    n = X[y==i+1,:].shape[0]\n",
    "    mean_vec = mean_vec.reshape(4,1) \n",
    "    overall_mean = overall_mean.reshape(4,1) \n",
    "    # 如上述公式进行计算\n",
    "    S_B += n * (mean_vec - overall_mean).dot((mean_vec - overall_mean).T)\n",
    "\n",
    "print('类间散布矩阵:\\n', S_B)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "-  <img src=\"img/l7.png\" alt=\"FAO\" width=\"230\" >"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "特征向量 1: \n",
      "[[-0.2049]\n",
      " [-0.3871]\n",
      " [ 0.5465]\n",
      " [ 0.7138]]\n",
      "特征值 1: 3.23e+01\n",
      "\n",
      "特征向量 2: \n",
      "[[-0.009 ]\n",
      " [-0.589 ]\n",
      " [ 0.2543]\n",
      " [-0.767 ]]\n",
      "特征值 2: 2.78e-01\n",
      "\n",
      "特征向量 3: \n",
      "[[-0.8844]\n",
      " [ 0.2854]\n",
      " [ 0.258 ]\n",
      " [ 0.2643]]\n",
      "特征值 3: 3.42e-15\n",
      "\n",
      "特征向量 4: \n",
      "[[-0.2234]\n",
      " [-0.2523]\n",
      " [-0.326 ]\n",
      " [ 0.8833]]\n",
      "特征值 4: 1.15e-14\n"
     ]
    }
   ],
   "source": [
    "#求解矩阵特征值，特征向量\n",
    "eig_vals, eig_vecs = np.linalg.eig(np.linalg.inv(S_W).dot(S_B))\n",
    "# 拿到每一个特征值和其所对应的特征向量\n",
    "for i in range(len(eig_vals)):\n",
    "    eigvec_sc = eig_vecs[:,i].reshape(4,1)   \n",
    "    print('\\n特征向量 {}: \\n{}'.format(i+1, eigvec_sc.real))\n",
    "    print('特征值 {:}: {:.2e}'.format(i+1, eig_vals[i].real))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 特征值与特征向量：\n",
    "- 特征向量：表示映射方向\n",
    "- 特征值：特征向量的重要程度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "特征值排序结果:\n",
      "\n",
      "32.27195779972981\n",
      "0.27756686384003953\n",
      "1.1483362279322388e-14\n",
      "3.422458920849769e-15\n"
     ]
    }
   ],
   "source": [
    "#特征值和特征向量配对\n",
    "eig_pairs = [(np.abs(eig_vals[i]), eig_vecs[:,i]) for i in range(len(eig_vals))]\n",
    "\n",
    "# 按特征值大小进行排序\n",
    "eig_pairs = sorted(eig_pairs, key=lambda k: k[0], reverse=True)\n",
    "\n",
    "print('特征值排序结果:\\n')\n",
    "for i in eig_pairs:\n",
    "    print(i[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "特征值占总体百分比:\n",
      "\n",
      "特征值 1: 99.15%\n",
      "特征值 2: 0.85%\n",
      "特征值 3: 0.00%\n",
      "特征值 4: 0.00%\n"
     ]
    }
   ],
   "source": [
    "print('特征值占总体百分比:\\n')\n",
    "eigv_sum = sum(eig_vals)\n",
    "for i,j in enumerate(eig_pairs):\n",
    "    print('特征值 {0:}: {1:.2%}'.format(i+1, (j[0]/eigv_sum).real))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "选择前两维特征"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "矩阵W:\n",
      " [[-0.2049 -0.009 ]\n",
      " [-0.3871 -0.589 ]\n",
      " [ 0.5465  0.2543]\n",
      " [ 0.7138 -0.767 ]]\n"
     ]
    }
   ],
   "source": [
    "W = np.hstack((eig_pairs[0][1].reshape(4,1), eig_pairs[1][1].reshape(4,1)))\n",
    "print('矩阵W:\\n', W.real)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(150, 2)"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 执行降维操作\n",
    "X_lda = X.dot(W)\n",
    "X_lda.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "原始数据可视化展示"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from matplotlib import pyplot as plt\n",
    "# 可视化展示\n",
    "def plot_step_lda():\n",
    "\n",
    "    ax = plt.subplot(111)\n",
    "    for label,marker,color in zip(\n",
    "        range(1,4),('^', 's', 'o'),('blue', 'red', 'green')):\n",
    "\n",
    "        plt.scatter(x=X[:,0].real[y == label],\n",
    "                y=X[:,1].real[y == label],\n",
    "                marker=marker,\n",
    "                color=color,\n",
    "                alpha=0.5,\n",
    "                label=label_dict[label]\n",
    "                )\n",
    "\n",
    "    plt.xlabel('X[0]')\n",
    "    plt.ylabel('X[1]')\n",
    "\n",
    "    leg = plt.legend(loc='upper right', fancybox=True)\n",
    "    leg.get_frame().set_alpha(0.5)\n",
    "    plt.title('Original data')\n",
    "\n",
    "    # 把边边角角隐藏起来\n",
    "    plt.tick_params(axis=\"both\", which=\"both\", bottom=\"off\", top=\"off\",  \n",
    "            labelbottom=\"on\", left=\"off\", right=\"off\", labelleft=\"on\")\n",
    "\n",
    "    # 为了看的清晰些，尽量简洁\n",
    "    ax.spines[\"top\"].set_visible(False)  \n",
    "    ax.spines[\"right\"].set_visible(False)\n",
    "    ax.spines[\"bottom\"].set_visible(False)\n",
    "    ax.spines[\"left\"].set_visible(False)    \n",
    "\n",
    "    plt.grid()\n",
    "    plt.tight_layout\n",
    "    plt.show()\n",
    "\n",
    "plot_step_lda()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "降维后数据可视化展示"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from matplotlib import pyplot as plt\n",
    "# 可视化展示\n",
    "def plot_step_lda():\n",
    "\n",
    "    ax = plt.subplot(111)\n",
    "    for label,marker,color in zip(\n",
    "        range(1,4),('^', 's', 'o'),('blue', 'red', 'green')):\n",
    "\n",
    "        plt.scatter(x=X_lda[:,0].real[y == label],\n",
    "                y=X_lda[:,1].real[y == label],\n",
    "                marker=marker,\n",
    "                color=color,\n",
    "                alpha=0.5,\n",
    "                label=label_dict[label]\n",
    "                )\n",
    "\n",
    "    plt.xlabel('LD1')\n",
    "    plt.ylabel('LD2')\n",
    "\n",
    "    leg = plt.legend(loc='upper right', fancybox=True)\n",
    "    leg.get_frame().set_alpha(0.5)\n",
    "    plt.title('LDA on iris')\n",
    "\n",
    "    # 把边边角角隐藏起来\n",
    "    plt.tick_params(axis=\"both\", which=\"both\", bottom=\"off\", top=\"off\",  \n",
    "            labelbottom=\"on\", left=\"off\", right=\"off\", labelleft=\"on\")\n",
    "\n",
    "    # 为了看的清晰些，尽量简洁\n",
    "    ax.spines[\"top\"].set_visible(False)  \n",
    "    ax.spines[\"right\"].set_visible(False)\n",
    "    ax.spines[\"bottom\"].set_visible(False)\n",
    "    ax.spines[\"left\"].set_visible(False)    \n",
    "\n",
    "    plt.grid()\n",
    "    plt.tight_layout\n",
    "    plt.show()\n",
    "\n",
    "plot_step_lda()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA\n",
    "\n",
    "# LDA\n",
    "sklearn_lda = LDA(n_components=2)\n",
    "X_lda_sklearn = sklearn_lda.fit_transform(X, y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "def plot_scikit_lda(X, title):\n",
    "\n",
    "    ax = plt.subplot(111)\n",
    "    for label,marker,color in zip(\n",
    "        range(1,4),('^', 's', 'o'),('blue', 'red', 'green')):\n",
    "\n",
    "        plt.scatter(x=X[:,0][y == label],\n",
    "                    y=X[:,1][y == label] * -1, # flip the figure\n",
    "                    marker=marker,\n",
    "                    color=color,\n",
    "                    alpha=0.5,\n",
    "                    label=label_dict[label])\n",
    "\n",
    "    plt.xlabel('LD1')\n",
    "    plt.ylabel('LD2')\n",
    "\n",
    "    leg = plt.legend(loc='upper right', fancybox=True)\n",
    "    leg.get_frame().set_alpha(0.5)\n",
    "    plt.title(title)\n",
    "\n",
    "    # hide axis ticks\n",
    "    plt.tick_params(axis=\"both\", which=\"both\", bottom=\"off\", top=\"off\",  \n",
    "            labelbottom=\"on\", left=\"off\", right=\"off\", labelleft=\"on\")\n",
    "\n",
    "    # remove axis spines\n",
    "    ax.spines[\"top\"].set_visible(False)  \n",
    "    ax.spines[\"right\"].set_visible(False)\n",
    "    ax.spines[\"bottom\"].set_visible(False)\n",
    "    ax.spines[\"left\"].set_visible(False)    \n",
    "\n",
    "    plt.grid()\n",
    "    plt.tight_layout\n",
    "    plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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4KqrruI3v/kN119/PTk5OVx99dV8/etf5+KLLwagoqKCGTNmUFlZSWNjI0cffXT0BU8irUkopXqMVaugsRH69bPf41Gb8Hg8FBcX85Of/IT777+fJ554ghNOOIGysjLKysp47733ePHFFzt9zpjgGcIzMzN58803ueyyy3jqqae48MILAbjhhhu4/vrree+99/jd735HQ0ND7IVPAg0SSqkewVeL8LW0FRba2kQsfRMffvghW7ZsaXtdVlbGcccdx759+1izZg1gJ/xt3LgRgH79+rVNVhs9ejS7du1i69atADzyyCNMmDABr9dLTU0NF110Effddx9lZWUA1NTUUFRUBMDDDz8cfaGTTJublFI9gq8W4fQxk53dXpv4xjeiO6bX6+WGG25g//79ZGZmcswxx/Dggw8yZ84cbrzxRmpqamhubuamm27ihBNOYNasWVx77bXk5uayZs0aFi5cyPTp02lububLX/4y1157LVVVVUyZMoWGhgaMMfzqV78CoKSkhOnTp1NUVMT48eP55JNP4nRlEkuDhFKqR1i/HoyBbds6bi8riz5InHrqqbz++uudtg8ePJh///vfnbZfdtllXHbZZW2vzzzzTK688soO+wwbNow333yz02enTJnClClToiuoizRIKKV6hAUL3C5B76R9EkoppULSIKGUUiokDRJKKaVC0iChlFIqJA0SSimlQtIgoZRy3V7vXkq3lfL0pqcp3VbKXm9ykt8VFxfzwgsvdNh23333MXfu3KiPuXLlSu6JMp1KXiw5RhJEg4RSylV7vXt5fefr1DfV0z+7P/VN9by+83Xe//R96hrrEho4Zs6cybJlyzpsW7ZsGTNnzuz2sy0tLUG3X3LJJcyfPz8u5Yvm/PGmQUIp5aoPPvuAnMwccrNyERFys3JpNa28suMVWk1rW+Couek66q+cAbNmdfyK4YZ8+eWX8+yzz7al+N62bRu7d+/m4MGDnHHGGYwbN47p06fjdXJ/jBw5kp/+9KecddZZ/O1vf+OPf/xjW0rwK664ArBrTlx//fUA7N27l6lTp3LSSSdx0kkntU3c++Uvf8mYMWMYM2YM9913X6dyGWP4wQ9+wJgxYzjxxBNZvnw5AKWlpUycOJFvfetbnHjiiVH/3pHQyXRKKVfVNNTQP7t/h221jbW0traSIRltgeOwqlr2jhjOyAEjOx4g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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_scikit_lda(X_lda_sklearn, title='Default LDA via scikit-learn')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
